﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using SdlDotNet.Input;
using SdlDotNet.Graphics;
using MonoPhysics;

namespace Monophysics_Demo
{
    partial class Demo
    {
        void UpdateAndDrawDraggingForce()
        {
            if (this.draging != null)
            {
                Vector pos = this.draging.Pos;
                PhysicContext npc = this.draging.PhysicStats;
                Vector mpos = new Vector(SdlDotNet.Input.Mouse.MousePosition);
                Vector f = (mpos - this.draging.HangPoint - pos) * 20;
                npc.PersistantForce = new Force(f, this.draging.HangPoint);
                //DrawForce(npc.PersistantForce, pos, this.draging.C);

                Point top = new Point(Convert.ToInt32(npc.PersistantForce.location.X + pos.X + npc.PersistantForce.force.X / 20), Convert.ToInt32(npc.PersistantForce.location.Y + pos.Y + npc.PersistantForce.force.Y / 20));
                SdlDotNet.Graphics.Primitives.Line l = new SdlDotNet.Graphics.Primitives.Line(new Point(Convert.ToInt32(npc.PersistantForce.location.X + pos.X), Convert.ToInt32(npc.PersistantForce.location.Y + pos.Y)), top);
                SdlDotNet.Graphics.Primitives.Circle c = new SdlDotNet.Graphics.Primitives.Circle(top, 2);
                Video.Screen.Draw(l, this.draging.C, AA, true);
                Video.Screen.Draw(c, this.draging.C, AA, true);
                this.draging.PhysicStats = npc;
            }
        }

        void DrawForce(Force f, Vector objpos, Color co, int div)
        {
            try
            {
                float fx = f.force.X * 10 / div; //* (float)//((f.force.X < 0) ? -Math.Log(1 + Math.Abs(f.force.X)) : Math.Log(1 + f.force.X));
                float fy = f.force.Y * 10 / div; //* (float)//((f.force.Y < 0) ? -Math.Log(1 + Math.Abs(f.force.Y)) : Math.Log(1 + f.force.Y));
                Point top = new Point(Convert.ToInt32(f.location.X + objpos.X + fx), Convert.ToInt32(f.location.Y + objpos.Y + fy));
                SdlDotNet.Graphics.Primitives.Line l = new SdlDotNet.Graphics.Primitives.Line(new Point(Convert.ToInt32(f.location.X + objpos.X), Convert.ToInt32(f.location.Y + objpos.Y)), top);
                SdlDotNet.Graphics.Primitives.Circle c = new SdlDotNet.Graphics.Primitives.Circle(top, 2);
                Video.Screen.Draw(l, co, AA, true);
                Video.Screen.Draw(c, co, AA, true);
            }
            catch { }
        }

        void DrawAABB(RectangleF pd, Color c)
        {
            SdlDotNet.Graphics.Primitives.Box b = new SdlDotNet.Graphics.Primitives.Box(Point.Round(pd.Location), Size.Round(pd.Size));
            Video.Screen.Draw(b, c, AA, false);
        }
        
        void DrawEnvDatas()
        {
            int height = 0;
            SdlDotNet.Graphics.Sprites.TextSprite ts = new SdlDotNet.Graphics.Sprites.TextSprite("", new SdlDotNet.Graphics.Font(@"C:\Windows\Fonts\Arial.ttf", 10), Color.White, false);

            ts.Text = "(+ - 0) Restitution coeff. = " + this.RestitutionCoeff.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(F1) Kill all.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(F2) Kill last.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;
            ts.Text = "(F3) Forces visible : " + this.showForces.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(F4) AABB visible : " + this.showAABB.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(F5) Can Draw concave : " + !this.convexOnly;
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(F10) Enable rotations: " + ImpulseSolver.AllowRotations.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;
            ts.Text = "(F11) Correct. by Mink. diff. : " + this.PhysicEngine.CorrectionsUseMink.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;
            ts.Text = "(F12) Broad phase : " + this.PhysicEngine.SweepAndPruneON.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(suppr) Kill selected.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(c) Show/Hide Sphere Trees.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(a) Set/Reset AntiAliazing.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "(m) Set/Reset Collisions prints.";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;
            ts.Text = "-------------------------";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "PAUSED :" + !this.PhysicEngine.Active;
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "Time step (dt , sec) :" + this.TimeStep.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "Physic update time (ms) : " + this.PhysT.ToString();
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "Nbr. objects : " + Demo.poly.Count;
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "Nbr. islands : " + this.PhysicEngine.NbrIsland;
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "Nbr. BroadPhase couples : " + this.PhysicEngine.NbrBroadPhaseResults;
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;

            ts.Text = "-------------------------";
            Video.Screen.Blit(ts, new Point(0, height));
            height += ts.Height;
            if (Demo.poly.Count != 0)
            {
                BoardPolygon BP = (this.Selected == null) ? Demo.poly[Demo.poly.Count - 1] : this.Selected;

                ts.Text = "Mass. = " + BP.M.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Inertia = " + BP.I.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Restitution = " + BP.Restitution.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Linear Velocity = " + BP.PhysicStats.V.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Angular Velocity = " + BP.PhysicStats.AngularVitess.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Nbr. forces = " + BP.PhysicStats.Forces.Count.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Absolute centroid pos. = " + BP.Pos.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;

                ts.Text = "Angular rotation state (grad) = " + BP.RotationGrad.ToString();
                Video.Screen.Blit(ts, new Point(0, height));
                height += ts.Height;
            }
        }
        void DrawsphereTrees()
        {
            //foreach (BoardPolygon bp in Demo.poly)
            //{
            if (Demo.poly.Count > 0)
            {
                //BoardPolygon bp = (this.Selected == null) ? Demo.poly[Demo.poly.Count - 1] : this.Selected;
                foreach (BoardPolygon bp in Demo.poly)
                {
                    if(this.printCircles)
                        DrawTreeNode(bp.Pos, ((Polygon)bp.Shape).Tree.Tree, 0);
                    //DrawSegs(bp.separatingEdge);
                }
            }

            //}
        }

        private int? DisplayedTreeH;
        private Color[] ccph;
        void DrawTreeNode(Vector pos, MonoPhysics.BinaryTree<Circle> node, int h)
        {
            if (node != null)
            {
                if (h == DisplayedTreeH || DisplayedTreeH == null || node.fg==null)
                {
                    Video.Screen.Draw(new SdlDotNet.Graphics.Primitives.Circle((short)(pos.X + node.Value.Center.X), (short)(pos.Y + node.Value.Center.Y), (short)node.Value.radius), this.ccph[h % 1000], AA, false);
                    Video.Screen.Draw(new SdlDotNet.Graphics.Primitives.Circle((short)(pos.X + node.Value.Center.X), (short)(pos.Y + node.Value.Center.Y), (short)1), this.ccph[h % 1000], AA, false);
                }
                DrawTreeNode(pos, node.fg, h + 1);
                DrawTreeNode(pos, node.fd, h + 1);
            }
        }

        void DrawSegs(List<SegmentD> segs)
        {
            foreach (SegmentD s in segs)
            {
                Video.Screen.Draw(new SdlDotNet.Graphics.Primitives.Line((short)s.Pt1.X, (short)s.Pt1.Y, (short)s.Pt2.X, (short)s.Pt2.Y), Color.Red, AA);
            }
        }
    }
}